package com.jzo2o.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.customer.dto.response.AddressBookResDTO;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.expcetions.ServerErrorException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.customer.enums.AddressDefaultStatusEnum;
import com.jzo2o.common.handler.UserInfoHandler;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.customer.mapper.AddressBookMapper;
import com.jzo2o.customer.model.domain.AddressBook;
import com.jzo2o.customer.model.dto.request.AddressBookPageQueryReqDTO;
import com.jzo2o.customer.model.dto.request.AddressBookUpsertReqDTO;
import com.jzo2o.customer.service.IAddressBookService;
import com.jzo2o.mysql.utils.PageUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 地址薄 服务实现类
 * </p>
 * @author itcast
 * @since 2023-07-06
 */
@Service
public class AddressBookServiceImpl extends ServiceImpl<AddressBookMapper, AddressBook> implements IAddressBookService {
    /**
     * 获取当前用户id
     */
    private final UserInfoHandler userInfoHandler;

    public AddressBookServiceImpl(UserInfoHandler userInfoHandler) {
        this.userInfoHandler = userInfoHandler;
    }

    private Long currentUserId() {
        if (ObjectUtils.isEmpty(userInfoHandler)) {
            throw new ServerErrorException("不能获取当前用户信息获取地址失败");
        } else {
            CurrentUserInfo currentUserInfo = userInfoHandler.currentUserInfo();
            if (ObjectUtils.isEmpty(currentUserInfo)) {
                throw new ServerErrorException("不能获取当前用户信息获取地址失败");
            } else {
                return currentUserInfo.getId();
            }
        }
    }

    @Override
    public List<AddressBookResDTO> getByUserIdAndCity(Long userId, String city) {

        List<AddressBook> addressBooks = lambdaQuery()
                .eq(AddressBook::getUserId, userId)
                .eq(AddressBook::getCity, city)
                .list();
        if (CollUtils.isEmpty(addressBooks)) {
            return new ArrayList<>();
        }
        return BeanUtils.copyToList(addressBooks, AddressBookResDTO.class);
    }

    private AddressBook getAddressBookByUpsertReqDTO(AddressBookUpsertReqDTO addressBookUpsertReqDTO) {
        // 解析经纬度
        String location = addressBookUpsertReqDTO.getLocation();
        Double lon = null, lat = null;
        if (!ObjectUtils.isEmpty(location)) {
            String[] pos = location.split(",");
            if (pos.length == 2) {
                lon = Double.parseDouble(pos[0]);
                lat = Double.parseDouble(pos[1]);
            }
        }

        // 构建AddressBook实体
        return AddressBook.builder()
                .userId(currentUserId())
                .name(addressBookUpsertReqDTO.getName())
                .phone(addressBookUpsertReqDTO.getPhone())
                .province(addressBookUpsertReqDTO.getProvince())
                .city(addressBookUpsertReqDTO.getCity())
                .county(addressBookUpsertReqDTO.getCounty())
                .address(addressBookUpsertReqDTO.getAddress())
                .isDefault(addressBookUpsertReqDTO.getIsDefault())
                .lon(lon).lat(lat).build();
    }

    @Override
    @Transactional
    public void insert(AddressBookUpsertReqDTO addressBookUpsertReqDTO) {
        // 取消其他默认地址
        if (addressBookUpsertReqDTO.getIsDefault() == AddressDefaultStatusEnum.DEFAULT.getStatus()) {
            lambdaUpdate()
                    .eq(AddressBook::getUserId, currentUserId())
                    .eq(AddressBook::getIsDefault, AddressDefaultStatusEnum.DEFAULT.getStatus())
                    .set(AddressBook::getIsDefault, AddressDefaultStatusEnum.NONE_DEFAULT.getStatus())
                    .update();
        }

        baseMapper.insert(getAddressBookByUpsertReqDTO(addressBookUpsertReqDTO));
    }

    @Override
    public PageResult<AddressBook> page(AddressBookPageQueryReqDTO addressBookPageQueryReqDTO) {
        Long userId = currentUserId();

        // mybatis-plus会自动筛选逻辑删除的字段
        LambdaQueryWrapper<AddressBook> queryWrapper = Wrappers.<AddressBook>lambdaQuery()
                .eq(AddressBook::getUserId, userId);
        Page<AddressBook> page = PageUtils.parsePageQuery(addressBookPageQueryReqDTO, AddressBook.class);

        Page<AddressBook> addressBookPage = baseMapper.selectPage(page, queryWrapper);
        return new PageResult<>(addressBookPage.getPages(), addressBookPage.getTotal(), addressBookPage.getRecords());
    }

    @Override
    @Transactional
    public void updateById(Long id, AddressBookUpsertReqDTO addressBookUpsertReqDTO) {
        AddressBook addressBook = baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(addressBook)) {
            throw new CommonException("地址id不存在无法更新");
        }

        addressBook = getAddressBookByUpsertReqDTO(addressBookUpsertReqDTO);
        addressBook.setId(id);

        baseMapper.updateById(addressBook);
    }

    @Override
    @Transactional
    public void updateDefault(Long id, int flag) {
        AddressBook addressBook = baseMapper.selectById(id);
        if (ObjectUtils.isEmpty(addressBook)) {
            throw new CommonException("地址id不存在无法更新");
        }

        // 取消原有默认地址
        lambdaUpdate()
                .eq(AddressBook::getUserId, currentUserId())
                .eq(AddressBook::getIsDefault, AddressDefaultStatusEnum.DEFAULT.getStatus())
                .set(AddressBook::getIsDefault, AddressDefaultStatusEnum.NONE_DEFAULT.getStatus())
                .update();

        // 设置指定id为默认地址
        lambdaUpdate()
                .eq(AddressBook::getId, id)
                .set(AddressBook::getIsDefault, AddressDefaultStatusEnum.DEFAULT.getStatus())
                .update();
    }

    @Override
    public AddressBook getDefaultAddress() {
        return lambdaQuery()
                .eq(AddressBook::getUserId, currentUserId())
                .eq(AddressBook::getIsDefault, AddressDefaultStatusEnum.DEFAULT.getStatus())
                .one();
    }
}